package poo.sistema;

import poo.util.*;

public class Gauss extends Sistema {

	private double[][] a;

	public Gauss(double[][] a, double[] y) {
		super(a, y);
		this.a = new double[a.length][a.length + 1];
		for (int i = 0; i < a.length; i++) {
			System.arraycopy(a[i], 0, this.a[i], 0, a.length);
			this.a[i][a.length - 1] = y[i];
		}
	}

	@Override
	public double[] risolvi() {
		triangolarizza();
		return calcolaSoluzione();
	}

	protected double[] calcolaSoluzione() {
		int n = getN();
		double[] x = new double[n];
		for (int i = n - 1; i >= 0; i--) {
			double sm = a[i][n];
			for (int j = i + 1; j < n - 1; j++)
				sm = sm - a[i][j] * x[j];
			x[i] = sm / a[i][i];
		}
		return x;
	}// calcolaSoluzione

	protected void triangolarizza() {
		int n = getN();
		for (int j = 0; j < n; j++) {
			// pivot=a[j][j] supposto !=0
			if (Mat.sufficientementeProssimi(a[j][j], 0D)) {
				int p = j + 1;
				for (; p < n; p++)
					if (!Mat.sufficientementeProssimi(a[p][j], 0D))
						break;
				if (p == n)
					throw new SistemaSingolare();
				// scambia riga j con riga p
				double[] tmp = a[j];
				a[j] = a[p];
				a[p] = tmp;
			}

			// azzera i coefficenti sulla colonna j
			for (int i = j + 1; i < n; i++)
				if (!Mat.sufficientementeProssimi(a[i][j], 0D)) {
					double coeff = a[i][j] / a[j][j];
					for (int k = j + 1; k <= n; k++)
						a[i][k] = a[i][k] - a[j][k] * coeff;
				}
		}
	}// triangolarizza

	public String toString() {
		int n = getN();
		StringBuilder sb = new StringBuilder(300);
		for (int i = 0; i < n; i++) {
			for (int j = 0; j <= n; j++)
				sb.append(String.format("%7.2f", a[i][j]));
			sb.append('\n');
		}
		return sb.toString();
	}// toString
}// GaussAlternativo
